#ifndef TEST_UTILS_H
#define TEST_UTILS_H

#include <string>
#include <filesystem>
#include <fstream>

namespace test_utils {

/**
 * @brief Get the binary directory path relative to the test executable
 * 
 * The binary directory is expected to be at: <project_root>/binary/
 * This function tries to locate it by:
 * 1. Using compile-time defined BINARY_DIR if available
 * 2. Otherwise, inferring from current working directory or executable path
 * 
 * @return std::string The path to the binary directory (with trailing slash)
 */
inline std::string GetBinaryDir() {
    // Try compile-time defined path first
    #ifdef TEST_BINARY_DIR
    std::string binary_dir = TEST_BINARY_DIR;
    if (!binary_dir.empty() && binary_dir.back() != '/') {
        binary_dir += "/";
    }
    return binary_dir;
    #else
    // Fallback: try to find binary directory relative to common build locations
    // This assumes tests are run from build/test/ or build/ directory
    std::filesystem::path current_path = std::filesystem::current_path();
    
    // Try build/test/ -> ../../binary/
    std::filesystem::path test_binary = current_path / ".." / ".." / "binary";
    if (std::filesystem::exists(test_binary) && std::filesystem::is_directory(test_binary)) {
        return test_binary.string() + "/";
    }
    
    // Try build/ -> ../binary/
    std::filesystem::path build_binary = current_path / ".." / "binary";
    if (std::filesystem::exists(build_binary) && std::filesystem::is_directory(build_binary)) {
        return build_binary.string() + "/";
    }
    
    // Try current directory
    std::filesystem::path current_binary = current_path / "binary";
    if (std::filesystem::exists(current_binary) && std::filesystem::is_directory(current_binary)) {
        return current_binary.string() + "/";
    }
    
    // Default fallback
    return "../binary/";
    #endif
}

/**
 * @brief Build full kernel binary path from filename
 * 
 * @param filename Kernel binary filename (e.g., "add_kernel.npubin")
 * @return std::string Full path to the kernel binary
 */
inline std::string GetKernelBinaryPath(const std::string& filename) {
    std::string binary_dir = GetBinaryDir();
    return binary_dir + filename;
}

/**
 * @brief Check if a file exists
 * 
 * @param filepath Full path to the file
 * @return true if file exists, false otherwise
 */
inline bool FileExists(const std::string& filepath) {
    return std::filesystem::exists(filepath) && std::filesystem::is_regular_file(filepath);
}

/**
 * @brief Check if kernel binary exists
 * 
 * @param filename Kernel binary filename
 * @return true if kernel binary exists, false otherwise
 */
inline bool KernelBinaryExists(const std::string& filename) {
    return FileExists(GetKernelBinaryPath(filename));
}

} // namespace test_utils

#endif // TEST_UTILS_H

